package main.java.DMDE.persistence.conversion;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import main.java.DMDE.model.*;
import main.java.DMDE.model.Class;
import main.java.DMDE.model.relationships.Association;
import main.java.DMDE.model.relationships.Inheritance;
import main.java.DMDE.model.relationships.RelationshipComponent;
import main.java.DMDE.persistence.DiagramXmlManager;
import main.java.common.IXmlFileManager;
import main.java.common.XmlFileManager;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class FSMToDMXmlAdapter {

	private IXmlFileManager xmlFileManager = new XmlFileManager();
	private DiagramXmlManager diagramXmlManager = new DiagramXmlManager();

	private List<Class> processedClasses = new ArrayList<Class>();

	public void convertXml(String fsmModelXmlRoute, String dmModelXmlRoute,
			String diagramName) throws Exception {
		String fsmRoute = fsmModelXmlRoute + "/" + diagramName + "-comp";
		String dmRoute = dmModelXmlRoute + "/" + diagramName + "-comp";
		Document fsmDocument = xmlFileManager.read(fsmRoute);
		Element rootElement = fsmDocument.getDocumentElement();
		Diagram diagram = new Diagram();
		diagram.setName(dmRoute.substring(dmRoute.lastIndexOf('/')));
		processFsmDiagramElement(diagram, rootElement);
		Document dmDocument = this.xmlFileManager.createDocument();
		try {
			Element laPapa = this.diagramXmlManager.getElementFromItem(diagram,
					dmDocument);
			dmDocument.appendChild(laPapa);
			this.xmlFileManager.write(dmDocument, dmRoute);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			processedClasses = new ArrayList<Class>();
		}

	}

	private void processFsmDiagramElement(Diagram dmDiagram,
			Element ermDiagramElement) {
		NodeList entities = ermDiagramElement.getElementsByTagName("interfaces")
				.item(0).getChildNodes();
		if (entities != null)
			for (int i = 0; i < entities.getLength(); i++) {
				Node node = entities.item(i);
				if (node == null || !(node instanceof Element))
					continue;
				Element entityElement = (Element) node;
				processFsmEntityElement(dmDiagram, entityElement);
			}
		NodeList hierarchies = ermDiagramElement
				.getElementsByTagName("transitions").item(0).getChildNodes();
		if (hierarchies != null)
			for (int i = 0; i < hierarchies.getLength(); i++) {
				Node node = hierarchies.item(i);
				if (node == null || !(node instanceof Element))
					continue;
				Element hierarchyElement = (Element) node;
				processFsmTransitionElement(dmDiagram, hierarchyElement);
			}
//		NodeList subdiagrams = ermDiagramElement
//				.getElementsByTagName("subDiagrams").item(0).getChildNodes();
//		if (subdiagrams != null)
//			for (int i = 0; i < subdiagrams.getLength(); i++) {
//				Node node = subdiagrams.item(i);
//				if (node == null || !(node instanceof Element))
//					continue;
//				Element subdiagramElement = (Element) node;
//				Diagram subDiagram = new Diagram();
//				dmDiagram.addSubDiagram(subDiagram);
//				processFsmDiagramElement(subDiagram, subdiagramElement);
//			}
	}

	private void processFsmTransitionElement(Diagram dmDiagram,
			Element hierarchyElement) {
		Class source = (Class) getEntityById(UUID.fromString(hierarchyElement
				.getAttribute("source")));
		Class destination = (Class) getEntityById(UUID.fromString(hierarchyElement
				.getAttribute("destination")));
		Association relationship = new Association(dmDiagram);
		RelationshipComponent a = new RelationshipComponent();
		a.setEntity(source);
		RelationshipComponent b = new RelationshipComponent();
		b.setEntity(destination);
		relationship.setComponentA(a);
		relationship.setComponentB(b);
		dmDiagram.addRelationship(relationship);
		relationship.setId(UUID.fromString(hierarchyElement.getAttribute("id")));
	}

	private Entity getEntityById(UUID id) {
		for (Entity entity : processedClasses) {
			if (entity.getId().equals(id))
				return entity;
		}
		return null;
	}

	private void processFsmEntityElement(Diagram dmDiagram,
			Element fsmEntityElement) {
		Class currentClass = new Class();
		processedClasses.add(currentClass);
		currentClass
				.setId(UUID.fromString(fsmEntityElement.getAttribute("id")));
		currentClass.setName(fsmEntityElement.getAttribute("name"));
		dmDiagram.addEntity(currentClass);
		NodeList attributes = fsmEntityElement
				.getElementsByTagName("components").item(0).getChildNodes();
		if (attributes != null)
			for (int i = 0; i < attributes.getLength(); i++) {
				Node node = attributes.item(i);
				if (node == null || !(node instanceof Element)) {
					continue;
				}
				Element attributeElem = (Element) node;
				processFsmAttribute(currentClass, attributeElem);
			}
	}

	private void processFsmAttribute(Class currentClass, Element attributeElem) {
		Attribute attribute = new Attribute();
		attribute.setName(attributeElem.getAttribute("name"));
		attribute.setVisibility(Visibility.PRIVATE);
		Type type = new Type();
		type.setName(attributeElem.getAttribute("type"));
		attribute.setType(type);
		attribute.setVisibility(Visibility.PRIVATE);
		currentClass.addAttribute(attribute);
	}
}
